{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Sales Agentic System with Strands SDK - (Orchestration - Worker Pattern) \n",
    "\n",
    "This project demonstrates how to build a multi-agent system using the [Strands SDK](https://strandsagents.com/latest/documentation/docs/) to automate the generation and sending of cold sales outreach emails for a fictional company, ComplAI, which offers an AI-powered SOC2 compliance SaaS tool. \n",
    "\n",
    "\n",
    "This project provides a practical foundation for building agentic systems for business processes like sales outreach using Strands SDK."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Importing necessary components from Strands SDK and other libraries.\n",
    "from strands.models import BedrockModel\n",
    "from strands import Agent, tool\n",
    "from dotenv import load_dotenv\n",
    "import os\n",
    "from typing import Dict\n",
    "\n",
    "# SendGrid imports for email functionality\n",
    "import sendgrid\n",
    "from sendgrid.helpers.mail import Email, To, Content\n",
    "from sendgrid import SendGridAPIClient\n",
    "from sendgrid.helpers.mail import Mail"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Load environment variables from a .env file.\n",
    "# `override=True` ensures that variables in .env take precedence over existing shell variables.\n",
    "load_dotenv(override=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Retrieve the AWS region name and sendgrid api key from environment variables.\n",
    "region_name = os.getenv(\"AWS_REGION_NAME\")\n",
    "sendgrid_api_key = os.getenv('SENDGRID_API_KEY')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# This function sends a test email using SendGrid to verify API key and setup.\n",
    "\n",
    "def send_test_email():\n",
    "    sg = sendgrid.SendGridAPIClient(api_key=sendgrid_api_key)\n",
    "    from_email = Email(\"iankisali@gmail.com\")\n",
    "    to_email = To(\"iankisali295@gmail.com\")\n",
    "    content = Content(\"text/plain\", \"This is a test email\")\n",
    "    mail = Mail(from_email, to_email, \"Test email\", content).get()\n",
    "    response = sg.client.mail.send.post(request_body=mail)\n",
    "    print(response.status_code)\n",
    "\n",
    "# Executing test email function\n",
    "send_test_email()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1. Agentic Workflow\n",
    "* **Multiple Agent Personas:** It defines and initializes three distinct sales agents—`Professional Sales Agent`, `Engaging Sales Agent`, and `Busy Sales Agent`—each with a unique `system_prompt` to guide their tone and style in generating cold emails (e.g., serious, witty, concise).\n",
    "* **Email Selection Agent:** A `sales_picker_agent` is introduced to evaluate and select the \"best\" cold email from those generated by the specialized agents, based on criteria like responsiveness."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define system prompts for different sales agent personas.\n",
    "# These instructions guide the LLM's behavior and tone.\n",
    "\n",
    "professional_instructions = \"You are a sales agent working for ComplAI, \\\n",
    "a company that provides a SaaS tool for ensuring SOC2 compliance and preparing for audits, powered by AI. \\\n",
    "You write professional, serious cold emails.\"\n",
    "\n",
    "witty_instructions = \"You are a humorous, engaging sales agent working for ComplAI, \\\n",
    "a company that provides a SaaS tool for ensuring SOC2 compliance and preparing for audits, powered by AI. \\\n",
    "You write witty, engaging cold emails that are likely to get a response.\"\n",
    "\n",
    "concise_instructions = \"You are a busy sales agent working for ComplAI, \\\n",
    "a company that provides a SaaS tool for ensuring SOC2 compliance and preparing for audits, powered by AI. \\\n",
    "You write concise, to the point cold emails.\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize the Bedrock model to be used by the agents.\n",
    "# We're using Anthropic Claude 3.5 Sonnet, a powerful general-purpose model.\n",
    "bedrock_model = BedrockModel(\n",
    "    model_id=\"anthropic.claude-3-5-sonnet-20240620-v1:0\",\n",
    "    region_name=region_name, \n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize different sales agents, each with a unique persona but using the same Bedrock model.\n",
    "\n",
    "# Professional Sales Agent: Focuses on serious and professional communication.\n",
    "professional_agent = Agent(\n",
    "        name=\"Professional Sales Agent\",\n",
    "        system_prompt=professional_instructions,\n",
    "        model=bedrock_model\n",
    ")\n",
    "\n",
    "# Engaging Sales Agent: Focuses on humorous and witty communication.\n",
    "witty_agent = Agent(\n",
    "        name=\"Engaging Sales Agent\",\n",
    "        system_prompt=witty_instructions,\n",
    "        model=bedrock_model\n",
    ")\n",
    "\n",
    "# Busy Sales Agent: Focuses on concise and direct communication.\n",
    "concise_agent = Agent(\n",
    "        name=\"Busy Sales Agent\",\n",
    "        system_prompt=concise_instructions,\n",
    "        model=bedrock_model\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Example: Have the professional agent write a cold sales email.\n",
    "response = professional_agent(\"Write a cold sales email\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Prepare a common message for all agents.\n",
    "message = \"Write a cold sales email\"\n",
    "\n",
    "# Make synchronous calls to all three agents to generate emails.\n",
    "# Note: These calls will execute sequentially, not in parallel.\n",
    "results = [\n",
    "    professional_agent(message),\n",
    "    witty_agent(message),\n",
    "    concise_agent(message),\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Print the available attributes/methods of the 'results' list\n",
    "print(dir(results))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Extract the content of the generated emails from the agent responses.\n",
    "# Each 'result' is an AgentResponse object, and we're accessing its 'message' attribute,\n",
    "# which typically contains a dictionary with 'content' and 'role'.\n",
    "outputs = [result.message for result in results]\n",
    "\n",
    "# Iterate through the extracted email contents and print them.\n",
    "for output in outputs:\n",
    "    print(output[\"content\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# sales picker prompt\n",
    "sales_picker_prompt = \"You pick the best cold sales email from the given options. \\\n",
    "Imagine you are a customer and pick the one you are most likely to respond to. \\\n",
    "Do not give an explanation; reply with the selected email only.\"\n",
    "\n",
    "# Initialize a 'sales_picker_agent' to select the best email from the generated options.\n",
    "sales_picker_agent = Agent(\n",
    "    name=\"Sales Email Picker\",\n",
    "    system_prompt=sales_picker_prompt,\n",
    "    model=bedrock_model\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "message = \"Write a cold sales email\"\n",
    "outputs = [result.message for result in results]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Concatenate all generated emails into a single string for the sales_picker_agent.\n",
    "# It joins the content of each email with \"Cold sales emails:\".\n",
    "emails = \"Cold sales emails:\".join([output[\"content\"][0][\"text\"] for output in outputs])\n",
    "#print(emails)\n",
    "\n",
    "# Have the sales_picker_agent select the best email.\n",
    "best = sales_picker_agent(emails)\n",
    "\n",
    "# Print the best selected email.\n",
    "print(f\"Best sales email:\\n{best.message}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2. Use of Tools\n",
    "* **External Function Integration:** The project shows how to integrate external functionalities as tools that agents can invoke. A `send_email` tool is created using SendGrid API to handle the actual sending of emails.\n",
    "* **Simplified Tool Creation:** Strands SDK's `@tool` decorator simplifies the process of making Python functions callable by agents, eliminating the need for manual JSON boilerplate for tool definitions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Display the professional_agent object.\n",
    "# In a Jupyter environment, this will show its representation.\n",
    "professional_agent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Steps 2 and 3: Tools and Agent Interactions\n",
    "\n",
    "Strands SDK simplifies tool creation with the `@tool` decorator, eliminating the need for manual JSON boilerplate for tool definitions.\n",
    "\n",
    "Simply wrap your function with the decorator `@tool`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def send_email(body: str):\n",
    "    \"\"\" Send out an email with the given body to all sales prospects \"\"\"\n",
    "    print(f\"\\n[Tool Call] Email Agent Engaged.\")\n",
    "    sg = sendgrid.SendGridAPIClient(api_key=sendgrid_api_key)\n",
    "    from_email = Email(\"iankisali@gmail.com\")\n",
    "    to_email = To(\"iankisali295@gmail.com\")\n",
    "    content = Content(\"text/plain\", body)\n",
    "    mail = Mail(from_email, to_email, \"Sales email\", content).get()\n",
    "    sg.client.mail.send.post(request_body=mail)\n",
    "    return {\"status\": \"success\"}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- This has automatically been converted into a tool, with the boilerplate json created\n",
    "- The `@tool` decorator handles the necessary internal representation for the LLM to understand and use this function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Display the `send_email` tool object to see its generated metadata.\n",
    "send_email"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### And you can also convert an Agent into a tool\n",
    "- This demonstrates the powerful \"Agent-as-a-Tool\" pattern, allowing hierarchical agent systems."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "async def professional_agent_tool(query: str) -> str:\n",
    "    \"\"\"\n",
    "    Consults a professional sales expert to get advice, strategies, or information related to sales,\n",
    "    customer engagement, product benefits, or market approaches.\n",
    "\n",
    "    Args:\n",
    "        query (str): The specific question or request for the sales expert.\n",
    "\n",
    "    Returns:\n",
    "        str: The advice, strategy, or information provided by the professional sales expert.\n",
    "    \"\"\"\n",
    "    print(f\"\\n[Tool Call] Delegating to Professional Sales Agent with query: '{query}'\")\n",
    "    response = professional_agent(query)\n",
    "    print(f\"[Tool Call] Professional Sales Agent responded: '{response}'\")\n",
    "    return str(response) # Ensure the response is a string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Display the `professional_agent_tool` object to see its generated metadata.\n",
    "professional_agent_tool"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3. Agent Collaboration via Tools and Handoffs\n",
    "* **Agent-as-a-Tool Pattern:** A key demonstration is the \"Agent-as-a-Tool\" pattern, where one Strands agent is wrapped in a `@tool` decorated function and then used by another agent. This is shown with `professional_agent_tool`, `engaging_agent_tool`, and `concise_agent_tool`, allowing a higher-level agent to delegate email generation to these specialized agents.\n",
    "* **Handoff Concept (Orchestration):**(not implemented) A `Sales Manager` agent is designed as an orchestrator. Its `system_prompt` guides it to:\n",
    "    * Utilize the email-writing agent tools (professional, engaging, concise) to generate multiple email drafts.\n",
    "    * Select the best email based on its judgment.\n",
    "    * Conceptually \"handoff\" to an `Email Manager` agent to format (write subject, convert to HTML) and send the chosen email. Although presented as a handoff, the `Sales Manager` ultimately orchestrates these actions by calling specific tools (`subject_writer_agent_tool`, `html_converter_agent_tool`, `send_html_email`) that perform the formatting and sending steps.\n",
    "\n",
    "#### So now we can gather all the tools together:\n",
    "\n",
    "- We're creating tools for each of our three email-writing agents (professional, engaging, concise) and a tool for sending emails.\n",
    "\n",
    "- A tool for each of our 3 email-writing agents\n",
    "\n",
    "- And a tool for our function to send emails"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "async def engaging_agent_tool(query: str) -> str:\n",
    "    \"\"\"\n",
    "    Consults an engaging sales expert to get advice, strategies, or information related to sales,\n",
    "    customer engagement, product benefits, or market approaches.\n",
    "\n",
    "    Args:\n",
    "        query (str): The specific question or request for the sales expert.\n",
    "\n",
    "    Returns:\n",
    "        str: The advice, strategy, or information provided by the professional sales expert.\n",
    "    \"\"\"\n",
    "    print(f\"\\n[Tool Call] Delegating to Engaging/Witty Sales Agent with query: '{query}'\")\n",
    "    response = witty_agent(query)\n",
    "    print(f\"[Tool Call] Engaging/Witty Sales Agent responded: '{response}'\")\n",
    "    return str(response)\n",
    "\n",
    "@tool\n",
    "async def concise_agent_tool(query: str) -> str:\n",
    "    \"\"\"\n",
    "    Consults a concise/busy sales expert to get advice, strategies, or information related to sales,\n",
    "    customer engagement, product benefits, or market approaches.\n",
    "\n",
    "    Args:\n",
    "        query (str): The specific question or request for the sales expert.\n",
    "\n",
    "    Returns:\n",
    "        str: The advice, strategy, or information provided by the professional sales expert.\n",
    "    \"\"\"\n",
    "    print(f\"\\n[Tool Call] Delegating to Concise/Busy Sales Agent with query: '{query}'\")\n",
    "    response = concise_agent(query)\n",
    "    print(f\"[Tool Call] Concise/Busy Sales Agent responded: '{response}'\")\n",
    "    return str(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compile all agent-as-tool wrappers and the email sending tool into a single list.\n",
    "tools = [professional_agent_tool, engaging_agent_tool, concise_agent_tool, send_email]\n",
    "\n",
    "# Display the list of compiled tools.\n",
    "tools"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### And now it's time for our Sales Manager - our planning agent\n",
    "- The Sales Manager agent will orchestrate the use of the email-writing tools and the email sending tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# sales manager instructions\n",
    "sales_manager_instructions =\"You are a sales manager working for ComplAI. You use the tools given to you to generate cold sales emails. \\\n",
    "You never generate sales emails yourself; you always use the tools. \\\n",
    "You try all 3 sales_agent tools once before choosing the best one. \\\n",
    "You pick the single best email and use the send_email tool to send the best email (and only the best email) to the user.\"\n",
    "\n",
    "# Initialize the Sales Manager agent with the defined instructions and tools.\n",
    "sales_manager = Agent(name=\"Sales Manager\", \n",
    "                    system_prompt=sales_manager_instructions, \n",
    "                    tools=tools,\n",
    "                    model=bedrock_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the message for the sales manager.\n",
    "message = \"Send a cold sales email addressed to 'Dear CEO'\"\n",
    "\n",
    "# Execute the sales manager agent with the message.\n",
    "# This will trigger the agent's reasoning, tool calls, and email selection/sending.\n",
    "result = sales_manager(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Handoffs represent a way an agent can delegate to an agent, passing control to it\n",
    "\n",
    "- Handoffs and Agents-as-tools are similar:\n",
    "\n",
    "- In both cases, an Agent can collaborate with another Agent\n",
    "\n",
    "- With tools, control passes back\n",
    "\n",
    "- With handoffs, control passes across\n",
    "\n",
    "- This section will likely introduce a different form of agent collaboration compared to the 'Agent-as-a-Tool' pattern, where one agent completely passes control to another to complete a task."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Instructions for a subject writer agent.\n",
    "subject_instructions = \"You can write a subject for a cold sales email. \\\n",
    "You are given a message and you need to write a subject for an email that is likely to get a response.\"\n",
    "\n",
    "# Instructions for an HTML converter agent.\n",
    "html_instructions = \"You can convert a text email body to an HTML email body. \\\n",
    "You are given a text email body which might have some markdown \\\n",
    "and you need to convert it to an HTML email body with simple, clear, compelling layout and design.\"\n",
    "\n",
    "# Initialize the Email Subject Writer agent.\n",
    "subject_writer_agent = Agent(name=\"Email subject writer\", \n",
    "                        system_prompt=subject_instructions, \n",
    "                        model=bedrock_model)\n",
    "\n",
    "# This tool wraps the subject_writer agent.\n",
    "@tool\n",
    "async def subject_writer_agent_tool(query: str) -> str:\n",
    "    print(f\"\\n[Tool Call] Subject writer agent tool engaged\")\n",
    "    response = subject_writer_agent(query)\n",
    "    print(f\"\\n[Tool Completed] Subject writer agent tool completed\")\n",
    "    return str(response)\n",
    "\n",
    "# Initialize the HTML Email Body Converter agent.\n",
    "html_converter = Agent(name=\"HTML email body converter\", \n",
    "                        system_prompt=html_instructions, \n",
    "                        model=bedrock_model)\n",
    "\n",
    "# This tool wraps the html_converter agent.\n",
    "@tool\n",
    "async def html_converter_agent_tool(query: str) -> str:\n",
    "    print(f\"\\n[Tool Call] HTML Converter agent tool engaged\")\n",
    "    response = html_converter(query)\n",
    "    print(f\"\\n[Tool Completed] HTML Converter agent tool completed\")\n",
    "    return str(response)                \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def send_html_email(subject: str, html_body: str) -> Dict[str, str]:\n",
    "    \"\"\" Send out an email with the given subject and HTML body to all sales prospects \"\"\"\n",
    "    sg = sendgrid.SendGridAPIClient(api_key=sendgrid_api_key)\n",
    "    from_email = Email(\"iankisali@gmail.com\") \n",
    "    to_email = To(\"iankisali295@gmail.com\")\n",
    "    content = Content(\"text/html\", html_body)\n",
    "    mail = Mail(from_email, to_email, subject, content).get()\n",
    "    sg.client.mail.send.post(request_body=mail)\n",
    "    return {\"status\": \"success\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compile the tools for the emailer agent.\n",
    "tools = [subject_writer_agent_tool, html_converter_agent_tool, send_html_email]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Display the list of tools.\n",
    "tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Email manager instructions - format and send email\n",
    "email_manager_instructions =\"You are an email formatter and sender. You receive the body of an email to be sent. \\\n",
    "You first use the subject_writer tool to write a subject for the email, then use the html_converter tool to convert the body to HTML. \\\n",
    "Finally, you use the send_html_email tool to send the email with the subject and HTML body.\"\n",
    "\n",
    "# Initialize the Emailer Agent, which acts as a coordinating agent for email formatting and sending.\n",
    "emailer_agent = Agent(\n",
    "    name=\"Email Manager\",\n",
    "    system_prompt=email_manager_instructions,\n",
    "    tools=tools,\n",
    "    model=bedrock_model)\n",
    "\n",
    "@tool\n",
    "async def email_agent_tool(query: str) -> str:\n",
    "    print(f\"\\n[Tool Call] HTML Converter agent tool engaged\")\n",
    "    response = emailer_agent(query)\n",
    "    print(f\"\\n[Tool Completed] HTML Converter agent tool completed\")\n",
    "    return str(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Now we have 3 tools and 1 handoff\n",
    "- The `sales_manager` agent will use the `emailer_agent` via a handoff mechanism or by calling it as a tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [subject_writer_agent_tool, html_converter_agent_tool, send_html_email, email_agent_tool]\n",
    "handoffs = [email_agent_tool]\n",
    "print(tools)\n",
    "print(handoffs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Sales manager instructions\n",
    "sales_manager_instructions = \"You are a sales manager working for ComplAI. You use the tools given to you to generate cold sales emails. \\\n",
    "You never generate sales emails yourself; you always use the tools. \\\n",
    "You try all 3 sales agent tools at least once before choosing the best one. \\\n",
    "You can use the tools multiple times if you're not satisfied with the results from the first try. \\\n",
    "You select the single best email using your own judgement of which email will be most effective. \\\n",
    "After picking the email, you handoff to the Email Manager agent to format and send the email.\"\n",
    "\n",
    "# Initialize the main Sales Manager agent, which orchestrates the entire process.\n",
    "sales_manager = Agent(\n",
    "    name=\"Sales Manager\",\n",
    "    system_prompt=sales_manager_instructions,\n",
    "    tools=tools,\n",
    "    model=bedrock_model)\n",
    "\n",
    "# Define the primary message for the sales manager.\n",
    "message = \"Send out a cold sales email addressed to Dear CEO from Kisali\"\n",
    "\n",
    "# Execute the sales manager, triggering the entire workflow.\n",
    "result = sales_manager(message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Print the final result from the sales manager.\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
